import org.travodds.*;
import types.*;
import java.lang.reflect.Field;

public class PubJava {
    public static void main(String[] args) {
        String path = "D:\\travodds\\travodds_java\\install\\lib";
        path += ";";
        path += "D:\\travodds\\build\\travoddsgen\\test\\generate_java\\output\\install\\lib";
        path += ";";
        System.setProperty("java.library.path", path);
        try {
            Field fieldSysPath = ClassLoader.class.getDeclaredField("sys_paths");
            fieldSysPath.setAccessible(true);
            fieldSysPath.set(null, null);
        } catch (Exception e) {
            e.printStackTrace();
        }
        System.loadLibrary("test_jnid");
        System.loadLibrary("travodds_jnid");
        // Create DomainParticipantFactory
        DomainParticipantFactoryProxy factory = DomainParticipantFactoryProxy.get_instance();
        if (factory == null) {
            System.err.println("Failed to get DomainParticipantFactory instance");
            return;
        }

        // Create DomainParticipant
        DomainParticipantProxy participant = factory.create_participant(0, DomainParticipantFactoryProxy.PARTICIPANT_QOS_DEFAULT(), null, StatusMaskProxy.NONE);
        if (participant == null) {
            System.err.println("Failed to create DomainParticipant");
            return;
        }

        // Create Publisher
        PublisherProxy publisher = participant.create_publisher(DomainParticipantProxy.PUBLISHER_QOS_DEFAULT(), null, StatusMaskProxy.NONE);
        if (publisher == null) {
            System.err.println("Failed to create Publisher");
            return;
        }

        // Register Type
        long typesupport = ComplexStructTypeSupport.get_instance();
        if (typesupport == 0) {
            System.err.println("Failed to get TypeSupport instance");
            return;
        }

        ReturnCodeProxy_t retcode = participant.registe_type("ComplexStructType", typesupport);
        if (retcode != ReturnCodeProxy_t.RETCODE_OK) {
            System.err.println("Failed to register Type");
            return;
        }
        
        // Create Topic
        TopicProxy topic = participant.create_topic("ComplexStructTopic", "ComplexStructType", DomainParticipantProxy.TOPIC_QOS_DEFAULT(), null, StatusMaskProxy.NONE);
        if (topic == null) {
            System.err.println("Failed to create Topic");
            return;
        }

        // Create DataWriter
        DataWriterProxy writer = publisher.create_datawriter(topic, PublisherProxy.DATAWRITER_QOS_DEFAULT(), null, StatusMaskProxy.NONE);
        if (writer == null) {
            System.err.println("Failed to create DataWriter");
            return;
        }

        // Create and populate data
        ComplexStruct data = new ComplexStruct();
        fillComplexStruct(data, 0);

        ComplexStructDataWriter complexStructDataWriter = new ComplexStructDataWriter(writer);

        // Publish data
        while (true) {
            try {
                System.in.read();
                Thread.sleep(1000); // Sleep for 1 second
            } catch (InterruptedException e) {
                e.printStackTrace();
            } catch (Exception e) {
                e.printStackTrace();
            }
            retcode = complexStructDataWriter.write(data, InstanceHandleProxy.HANDLE_NIL());
            if (retcode != ReturnCodeProxy_t.RETCODE_OK) {
                System.err.println("Failed to write data: " + retcode);
                break;
            }
            System.out.println("Data published.");
        }
    }

    private static void fillSimpleStruct(SimpleStruct data, int offset) {
        data.setEnumVal(EnumExample.RED);
        data.setBVal((char) ((1 + offset) % 2));
        data.setCVal((char) ('A' + (2 + offset) % 26));
        data.setOVal((short) (3 + offset));
        data.setInt8Val((char) (4 + offset));
        data.setUint8Val((short) (5 + offset));
        data.setShortVal((short) (7 + offset));
        data.setUshortVal(8 + offset);
        data.setInt16Val((short) (9 + offset));
        data.setUint16Val(10 + offset);
        data.setLongVal(11 + offset);
        data.setUlongVal(12L + offset);
        data.setInt32Val(13 + offset);
        data.setUint32Val(14L + offset);
        data.setFloatVal(15.0f + offset);
        data.setDoubleVal(16.0 + offset);
        data.setLlVal(18L + offset);
        data.setInt64Val(20L + offset);
        data.setBArrVal("String_" + (45 + offset));

        // Populate array members
        data.setenumArrVal(0, EnumExample.RED);
        data.setenumArrVal(0, EnumExample.BLUE);

        char[] booleanArr = new char[3];
        for (int i = 0; i < booleanArr.length; i++) {
            booleanArr[i] = (char) ((23 + i + offset) % 2);
        }
        data.setBArrVal(String.valueOf(booleanArr));

        char[] charArr = data.getCArrVal().toCharArray();
        for (int i = 0; i < charArr.length; i++) {
            charArr[i] = (char) ('A' + (24 + i + offset) % 26);
        }

        short[] octetArr = data.getOArrVal();
        for (int i = 0; i < octetArr.length; i++) {
            octetArr[i] = (short) (25 + i + offset);
        }

        char[] int8Arr = data.getInt8ArrVal().toCharArray();
        for (int i = 0; i < int8Arr.length; i++) {
            int8Arr[i] = (char) (26 + i + offset);
        }

        short[] uint8Arr = data.getUint8ArrVal();
        for (int i = 0; i < uint8Arr.length; i++) {
            uint8Arr[i] = (short) (27 + i + offset);
        }

        // char[] wcharArr = new char[8];
        // for (int i = 0; i < wcharArr.length; i++) {
        //     wcharArr[i] = (char) ('A' + (28 + i + offset) % 26);
        // }
        // data.setCArrVal(String.valueOf(wcharArr));

        short[] shortArr = data.getShortArrVal();
        for (int i = 0; i < shortArr.length; i++) {
            shortArr[i] = (short) (29 + i + offset);
        }

        int[] ushortArr = data.getUshortArrVal();
        for (int i = 0; i < ushortArr.length; i++) {
            ushortArr[i] = 30 + i + offset;
        }

        short[] int16Arr = data.getInt16ArrVal();
        for (int i = 0; i < int16Arr.length; i++) {
            int16Arr[i] = (short) (31 + i + offset);
        }

        int[] uint16Arr = data.getUint16ArrVal();
        for (int i = 0; i < uint16Arr.length; i++) {
            uint16Arr[i] = 32 + i + offset;
        }

        int[] longArr = data.getLongArrVal();
        for (int i = 0; i < longArr.length; i++) {
            longArr[i] = 33 + i + offset;
        }

        long[] ulongArr = data.getUlongArrVal();
        for (int i = 0; i < ulongArr.length; i++) {
            ulongArr[i] = 34L + i + offset;
        }

        int[] int32Arr = data.getInt32ArrVal();
        for (int i = 0; i < int32Arr.length; i++) {
            int32Arr[i] = 35 + i + offset;
        }

        long[] uint32Arr = data.getUint32ArrVal();
        for (int i = 0; i < uint32Arr.length; i++) {
            uint32Arr[i] = 36L + i + offset;
        }

        float[] floatArr = data.getFloatArrVal();
        for (int i = 0; i < floatArr.length; i++) {
            floatArr[i] = 37.0f + i + offset;
        }

        double[] doubleArr = data.getDoubleArrVal();
        for (int i = 0; i < doubleArr.length; i++) {
            doubleArr[i] = 38.0 + i + offset;
        }

        long[] llArr = data.getLlArrVal();
        for (int i = 0; i < llArr.length; i++) {
            llArr[i] = 40L + i + offset;
        }

        long[] int64Arr = data.getInt64ArrVal();
        for (int i = 0; i < int64Arr.length; i++) {
            int64Arr[i] = 42L + i + offset;
        }
        data.setInt64ArrVal(int64Arr);

        // long[] uint64Arr = new long[22];
        // for (int i = 0; i < uint64Arr.length; i++) {
        //     uint64Arr[i] = 43L + i + offset;
        // }
        // data.setUint64ArrVal(uint64Arr);

        // Populate sequence members
        CharSeq bSeq = new CharSeq();
        bSeq.reserve(2);
        for (int i = 0; i < 2; i++) {
            bSeq.add((char) ((24 + i + offset) % 2));
        }
        data.setBSeq(bSeq);

        CharSeq cSeq = new CharSeq();
        cSeq.reserve(3);
        for (int i = 0; i < 3; i++) {
            cSeq.add((char) ('A' + (25 + i + offset) % 26));
        }
        data.setCSeq(cSeq);

        OctetSeq oSeq = new OctetSeq();
        oSeq.reserve(4);
        for (int i = 0; i < 4; i++) {
            oSeq.add((short) (26 + i + offset));
        }
        data.setOSeq(oSeq);

        CharSeq int8Seq = new CharSeq();
        int8Seq.reserve(5);
        for (int i = 0; i < 5; i++) {
            int8Seq.add((char) (27 + i + offset));
        }
        data.setInt8Seq(int8Seq);

        OctetSeq uint8Seq = new OctetSeq();
        uint8Seq.reserve(6);
        for (int i = 0; i < 6; i++) {
            uint8Seq.add((short) (28 + i + offset));
        }
        data.setUint8Seq(uint8Seq);

        CharSeq wcharSeq = new CharSeq();
        wcharSeq.reserve(7);
        for (int i = 0; i < 7; i++) {
            wcharSeq.add((char) ('A' + (29 + i + offset) % 26));
        }
        data.setCSeq(wcharSeq);

        ShortSeq shortSeq = new ShortSeq();
        shortSeq.reserve(8);
        for (int i = 0; i < 8; i++) {
            shortSeq.add((short) (30 + i + offset));
        }
        data.setShortSeq(shortSeq);

        UShortSeq ushortSeq = new UShortSeq();
        ushortSeq.reserve(9);
        for (int i = 0; i < 9; i++) {
            ushortSeq.add(31 + i + offset);
        }
        data.setUshortSeq(ushortSeq);

        ShortSeq int16Seq = new ShortSeq();
        int16Seq.reserve(10);
        for (int i = 0; i < 10; i++) {
            int16Seq.add((short) (32 + i + offset));
        }
        data.setInt16Seq(int16Seq);

        UShortSeq uint16Seq = new UShortSeq();
        uint16Seq.reserve(11);
        for (int i = 0; i < 11; i++) {
            uint16Seq.add(33 + i + offset);
        }
        data.setUint16Seq(uint16Seq);

        LongSeq longSeq = new LongSeq();
        longSeq.reserve(12);
        for (int i = 0; i < 12; i++) {
            longSeq.add(34 + i + offset);
        }
        data.setLongSeq(longSeq);

        ULongSeq ulongSeq = new ULongSeq();
        ulongSeq.reserve(13);
        for (int i = 0; i < 13; i++) {
            ulongSeq.add(35L + i + offset);
        }
        data.setUlongSeq(ulongSeq);

        LongSeq int32Seq = new LongSeq();
        int32Seq.reserve(14);
        for (int i = 0; i < 14; i++) {
            int32Seq.add(36 + i + offset);
        }
        data.setInt32Seq(int32Seq);

        ULongSeq uint32Seq = new ULongSeq();
        uint32Seq.reserve(15);
        for (int i = 0; i < 15; i++) {
            uint32Seq.add(37L + i + offset);
        }
        data.setUint32Seq(uint32Seq);

        FloatSeq floatSeq = new FloatSeq();
        floatSeq.reserve(16);
        for (int i = 0; i < 16; i++) {
            floatSeq.add(38.0f + i + offset);
        }
        data.setFloatSeq(floatSeq);

        DoubleSeq doubleSeq = new DoubleSeq();
        doubleSeq.reserve(17);
        for (int i = 0; i < 17; i++) {
            doubleSeq.add(39.0 + i + offset);
        }
        data.setDoubleSeq(doubleSeq);

        LongLongSeq llSeq = new LongLongSeq();
        llSeq.reserve(19);
        for (int i = 0; i < 19; i++) {
            llSeq.add(41L + i + offset);
        }
        data.setLlSeq(llSeq);

        LongLongSeq int64Seq = new LongLongSeq();
        int64Seq.reserve(21);
        for (int i = 0; i < 21; i++) {
            int64Seq.add(43L + i + offset);
        }
        data.setInt64Seq(int64Seq);

        // LongLongSeq uint64Seq = new LongLongSeq();
        // uint64Seq.reserve(22);
        // for (int i = 0; i < 22; i++) {
        //     uint64Seq.add(44L + i + offset);
        // }
        // data.setUint64Seq(uint64Seq);
    }

    private static void fillComplexStruct(ComplexStruct data, int offset) {
        data.setName("ParentName_" + offset);
        SimpleStruct structMem = data.getStructMem();
        fillSimpleStruct(structMem, 1 + offset);

        for (int i = 0; i < 2; i++) {
            SimpleStruct curEle = data.getstructArrayMem(i);
            fillSimpleStruct(curEle, 2 + i + offset);
        }

        SimpleStructSeq structSeqMem = data.getStructSeqMem();
        structSeqMem.reserve(16);
        for (int i = 0; i < 16; i++) {
            SimpleStruct seqItem = new SimpleStruct();
            fillSimpleStruct(seqItem, 3 + i + offset);
            structSeqMem.add(seqItem);
        }

        StringSimpleStructMap structMapMem = data.getStructMapMem();
        for (int i = 0; i < 3; i++) {
            SimpleStruct mapItem = new SimpleStruct();
            fillSimpleStruct(mapItem, 4 + i + offset);
            structMapMem.put("Key_" + (4 + i + offset), mapItem);
        }
    }
}
